package comm

import (
	"d-serv-go/server/core/bean"
	"d-serv-go/server/core/conf"
	"d-serv-go/server/core/config"
	"d-serv-go/server/core/consts"
	"d-serv-go/server/core/db"
	"d-serv-go/server/core/log"
	"d-serv-go/server/core/serv"
	"d-serv-go/server/core/util"
	"github.com/kirinlabs/utils/str"
	"io/ioutil"
	"strings"
)

type InfoServ struct {
	serv.CommServ
}

func (p *InfoServ) SysInfo(paramBean *db.ParamBean) *bean.OutBean {
	out := bean.NewOutBean()
	context := db.Ctx()
	vars := bean.NewBean("")
	vars.SetMap(db.VarMgr.GetOrgMap())
	vars.SetMap(db.VarMgr.GetConfMap())
	vars.SetMap(db.VarMgr.GetDateMap())
	// 设置socket的url
	vars.Set("@SOCKET.IO_URL@", "ws://xxxxxxxxx")
	userBean := context.GetUserBean()
	if userBean != nil {
		// 设置用户的样式
		style, _ := db.ServDao.FindById("SY_ORG_USER_STYLE", userBean.GetId(), false)
		if style == nil {
			style := bean.NewBean("")
			style.Set("SS_ID", userBean.GetId())
			style.Set("S_PUBLIC", 0)
			style.Set("S_FLAG", 1)
			style.Set("S_USER", userBean.GetId())
			style.Set("S_MTIME", util.DateUtil.GetDatetimeTS())
			paramBean := db.NewParamBean(style)
			db.ServDao.Save("SY_ORG_USER_STYLE", paramBean)
		}
		vars.Set("@SS_STYLE_MENU@", style.GetStr("SS_STYLE_MENU"))
	}
	out.Set("data", vars)
	return out
}

func (p *InfoServ) SocketIoInfo(paramBean *db.ParamBean) *bean.OutBean {
	out := bean.NewOutBean()
	out.Set("@SOCKET.IO_URL@", "ws://xxxxxxx")
	return out
}

func (p *InfoServ) Dict(paramBean *db.ParamBean) *bean.OutBean {
	out := bean.NewOutBean()
	var dictId string
	if paramBean.Contains("DICT_ID") {
		dictId = paramBean.GetStr("DICT_ID")
	} else {
		dictId = paramBean.GetId()
	}
	if len(dictId) == 0 {
		log.Error("empty dict ID!")
		return out
	}
	showFlag := false

	//不需要Session的字典列表
	dictIds := strings.Split(conf.ConfMgr.GetStr("SY_SERV_DICT_NOSESSION", "SY_ORG_CMPY"), consts.SEPARATOR)
	if util.IsIn(dictIds, dictId) { //判断是否在允许的配置中
		showFlag = true
	} else {
		userBean := db.Ctx().GetUserBean()
		if userBean != nil { //有Session可以获取字典
			showFlag = true
		}
	}
	//获取字典信息，支持PID和LEVEL层级
	if showFlag { //可以获取字典信息
		bThread := false
		if !paramBean.IsEmpty("_extWhere") { //设置线程变量
			db.Ctx().SetStr(consts.THREAD_DICT_EXT_WHERE, paramBean.GetStr("_extWhere"))
			bThread = true
		}
		if str.StartsWith(dictId, "@") {
			// TODO 待择日找个例子
			out = db.DictMgr.GetDynaItemList(dictId[1:], paramBean)
		} else {
			dict := db.DictMgr.GetDict(dictId)
			if dict != nil {
				copyDict := dict.CopyOf([]string{"DICT_ID", "DICT_NAME", "DICT_DIS_LAYER", "DICT_CHILD_ID", "DICT_TYPE"})
				out.SetMap(copyDict.GetMap())
				pId := paramBean.GetStr("PID")
				if len(pId) > 0 && str.StartsWith(pId, "@") { //系统变量
					pId = serv.ServUtils.ReplaceSysVars(pId)
				}
				//显示层级， 优先取外部参数，如果没有去字典定义配置，，如果没有则层级为0，取全部
				layer := paramBean.GetInt("LEVEL", dict.GetInt("DICT_DIS_LAYER"))
				showPid := paramBean.GetBool("SHOWPID") //支持设定输出信息是否带PID节点信息，缺省不带
				out.Set(consts.CHILD_NODE, db.DictMgr.GetTreeList(dictId, pId, layer, showPid))
			}
		}
		if bThread { //恢复线程变量
			db.Ctx().SetStr(consts.THREAD_DICT_EXT_WHERE, nil)
		}
	} else {
		out.Set(bean.TO_LOGIN, true)
	}
	return out
}

func (p *InfoServ) Menu(paramBean *db.ParamBean) *bean.OutBean {
	menu := bean.NewOutBean()
	userBean := db.Ctx().GetUserBean()
	if userBean == nil { //用户必须登录才可以获取菜单
		return menu
	}
	userState := db.UserMgr.GetUserState(userBean.GetCode())
	if userState == nil {
		log.Error("异常::InfoServ::menu::userBean::{}::paramBean::{}", userBean, paramBean)
		menu.SetError("查询菜单异常！")
	} else if userState.IsEmpty("MENU_TIME") {
		db.MenuMgr.MenuToCache(userBean.GetCode())
	}
	// 先从缓存获取菜单
	menuTree := db.UserMgr.GetCacheMenuList(userBean.GetCode())
	if paramBean.IsNotEmpty("PID") { //设定了动态取一部分菜单信息

		db.DictMgr.HandleTree(menuTree, func(data *bean.Bean) {
			if data.GetStr("ID") == paramBean.GetStr("PID") { //取当前节点下所有的子孙
				paramBean.Set(consts.CHILD_NODE, data.GetBeans(consts.CHILD_NODE))
				paramBean.Set("PARENT_NODE", data)
			}
		})
		menuTree = paramBean.GetBeans(consts.CHILD_NODE)
	}
	if !paramBean.Contains(consts.LEFTMENU) {
		menu.Set(consts.TOPMENU, menuTree)
	} else {
		menu.Set(consts.LEFTMENU, menuTree)
	}
	menu.Set("PARENT_NODE", paramBean.GetBean("PARENT_NODE"))
	return menu
}

func (p *InfoServ) Scripts(paramBean *db.ParamBean) *bean.OutBean {
	outBean := bean.NewOutBean()
	pro := config.Instance.AppDir
	servId := paramBean.GetStr("servId")
	outBean.Set("scripts", "{}")
	if len(servId) == 0 {
		outBean.SetError("参数：servId不可以为空")
	} else {
		strs := strings.Split(strings.ToLower(servId), "_")
		fileName := pro +util.Separator + "scripts" + util.Separator + strs[0] + util.Separator + servId + ".js"
		bytes, err := ioutil.ReadFile(fileName)
		if err != nil {
			outBean.SetError(servId + "加载script，发现文件不存在")
		} else {
			outBean.Set("scripts", string(bytes))
		}
	}
	return outBean
}

func (p *InfoServ) GetDictAcls(paramBean *db.ParamBean) *bean.OutBean {
	dictId := paramBean.GetStr("dictId")
	userBean := db.Ctx().GetUserBean()
	userCode := userBean.GetCode()
	dictAcls := db.AclMgr.GetDictAcls2(dictId, userCode)
	out := bean.NewOutBean()
	out.Set("dictAcls", dictAcls)
	return out.SetOk("")
}
